﻿using System;
using System.Web;
using System.Web.Caching;
using Eneta.Portal.Common.Definitions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;

namespace Eneta.Portal.Common.Repository
{
	/// <summary>
	/// Class for base repository. All repositories are inherited from this class. This class provides 
	/// also common querying methods for extended repositories.
	/// </summary>
	public abstract class BaseRepository
	{
		/// <summary>
		/// Gets or sets the site id.
		/// </summary>
		public Guid SiteId { get; protected set;}

		/// <summary>
		/// Gets or sets the web id.
		/// </summary>
		public Guid WebId  { get; protected set;}

		/// <summary>
		/// Initializes a new instance of the <see cref="BaseRepository"/> class.
		/// </summary>
		protected BaseRepository(SPWeb web)
		{
			if (web == null)
				return;
			SiteId = web.Site.ID;
			WebId = web.ID;
		}

		protected string GetWebUrl(SPSite site, string webUrl)
		{
			webUrl = webUrl.ToLower().Replace(site.Url.ToLower(), string.Empty);
			if(!string.IsNullOrEmpty(site.Url))
				if (!webUrl.StartsWith("/"))
					webUrl = "/" + webUrl;
			Logger.LogInfo("SITE URL: " + site.Url);
			Logger.LogInfo("WEB URL: " + webUrl);
			return webUrl;
		}

		/// <summary>
		/// Queries the list for item by given field value.
		/// </summary>
		/// <param name="list">The list to query.</param>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="fieldValue">The field value.</param>
		protected SPListItem QueryItemByFieldValue(SPList list, string fieldName, string fieldValue)
		{
			var items = QueryItemsByFieldValue(list, fieldName, fieldValue, 1);
			if (items == null)
				return null;
			if (items.Count == 0)
				return null;
			return items[0];
		}

		protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue)
		{
			return QueryItemsByFieldValue(list, fieldName, fieldValue, 0);
		}
		protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue, int limit)
		{
			return QueryItemsByFieldValue(list, fieldName, fieldValue, string.Empty, false, 0);
		}
		protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue, string orderBy, bool ascending, int limit)
		{
			var fieldType = list.Fields[fieldName].TypeAsString;
			var queryString = "<Where><Eq><FieldRef Name='{0}'/><Value Type='{1}'>{2}</Value></Eq></Where>";
			if(!string.IsNullOrEmpty(orderBy))
			{
				queryString += "<OrderBy><FieldRef Name='" + orderBy + "' Ascending='";
				if (ascending)
					queryString += "True";
				else
					queryString += "False";
				queryString += "' /></OrderBy>";
			}
			queryString = string.Format(queryString, fieldName, fieldType, fieldValue);

			return ExecuteQuery(list, queryString, limit);
		}

		protected SPListItemCollection ExecuteQuery(SPList list, string queryString)
		{
			return ExecuteQuery(list, queryString, 0);
		}
		protected SPListItemCollection ExecuteQuery(SPList list, string queryString, int limit)
		{
			//Logger.LogInfo("ExecuteQuery(): List : " + list.Title,GetType().ToString());
			//Logger.LogInfo("ExecuteQuery(): Query: " + queryString, GetType().ToString());

			try
			{
				var query = new SPQuery
								{
									Query = queryString
								};

				if (limit > 0)
					query.RowLimit = (uint)limit;

				var items = list.GetItems(query);
				//Logger.LogInfo("ExecuteQuery(): Results: " + items.Count, GetType().ToString());

				return items;
			}
			catch(Exception ex)
			{
				Logger.LogException(ex);
				throw;
			}
		}

		protected SPListItemCollection GetPendingItems(SPList list, SPContentTypeId contentTypeId, string order, bool ascending)
		{
			return GetItemsByModerationStatus(list, Resources.ModerationStatusPending, contentTypeId, order, ascending);
		}

		protected SPListItemCollection GetApprovedItems(SPList list, SPContentTypeId contentTypeId, string order, bool ascending)
		{
			return GetItemsByModerationStatus(list, Resources.ModerationStatusApproved, contentTypeId, order, ascending);            
		}

		protected SPListItemCollection GetApprovedItems(SPList list, string order, bool ascending)
		{
			return GetItemsByModerationStatus(list, Resources.ModerationStatusApproved, order, ascending);
		}

		protected string GetRssHeader(string title, string link)
		{
			var header = @"
					<rss 
						xmlns:content=""http://purl.org/rss/1.0/modules/content/"" 
						xmlns:wfw=""http://wellformedweb.org/CommentAPI/"" 
						xmlns:dc=""http://purl.org/dc/elements/1.1/"" 
						xmlns:atom=""http://www.w3.org/2005/Atom"" 
						xmlns:sy=""http://purl.org/rss/1.0/modules/syndication/"" 
						xmlns:slash=""http://purl.org/rss/1.0/modules/slash/"" 
						version=""2.0"">
						<channel>
							<title>{0}</title>
							<link>{1}</link>
							<description></description>
							<lastBuildDate>{2}</lastBuildDate>
							<generator>Eneta portaal</generator>
							<language>et</language>
							<sy:updatePeriod>hourly</sy:updatePeriod>
							<sy:updateFrequency>1</sy:updateFrequency>
				";
			//<atom10:link 
			//    xmlns:atom10=""http://www.w3.org/2005/Atom"" 
			//    rel=""self"" 
			//    href=""http://feeds.feedburner.com/wekeroad/EeKc"" 
			//    type=""application/rss+xml"" />
			header = string.Format(header, title, link, DateTime.Now.ToString("r"));

			return header;
		}

		protected string GetRssFooter()
		{
			return "</channel></rss>";
		}

		private SPListItemCollection GetItemsByModerationStatus(SPList list, string status, string orderBy, bool ascending)
		{
			string query = "<Where>";
			query += "<Eq><FieldRef Name='_ModerationStatus'/><Value Type='ModStat'>{0}</Value></Eq>";
			query += "</Where>";
			query = string.Format(query, status);

			if (!string.IsNullOrEmpty(orderBy))
			{
				query += "<OrderBy><FieldRef Name='" + orderBy + "' ";
				if (!ascending)
					query += "Ascending='False'";
				query += "/></OrderBy>";
			}

			return ExecuteQuery(list, query);
		}

		private SPListItemCollection GetItemsByModerationStatus(SPList list, string status, SPContentTypeId contentTypeId, string orderBy, bool ascending)
		{
			var ctName = ContentTypes.GetName(contentTypeId.ToString());
			string query = "<Where><And>";
			query += "<Eq><FieldRef Name='_ModerationStatus'/><Value Type='ModStat'>{0}</Value></Eq>";
			query += "<Eq><FieldRef Name='ContentType'/><Value Type='Text'>{1}</Value></Eq>";
			query += "</And></Where>";
			query = string.Format(query, status, ctName);

			if (!string.IsNullOrEmpty(orderBy))
			{
				query += "<OrderBy><FieldRef Name='" + orderBy + "' ";
				if (!ascending)
					query += "Ascending='False'";
				query += "/></OrderBy>";
			}

			return ExecuteQuery(list, query);
		}


		protected SPListItem GetPreviuosItemById(SPList list, int itemId)
		{
			throw new NotImplementedException();
		}

		protected SPListItem GetNextItemById(SPList list, int itemId)
		{
			throw new NotImplementedException();
		}

		#region Caching
		protected T GetFromCache<T>(string cacheKey) where T : class
		{
			var context = HttpContext.Current;

			if (context == null)
				return null;
			if (context.Cache[cacheKey] == null)
				return null;

			return context.Cache[cacheKey] as T;
		}

		protected void SaveToCache(string cacheKey, object o)
		{
			SaveToCache(cacheKey, o, 0);
		}

		protected void SaveToCache(string cacheKey, object o, int timeToLive)
		{
			if (HttpContext.Current == null)
				return;
			var cache = HttpContext.Current.Cache;
			if (o == null)
			{
				cache.Remove(cacheKey);
				return;
			}

			if (timeToLive <= 0)
			{
				cache.Insert(cacheKey, o);
				return;
			}
			cache.Insert(cacheKey, o,null, DateTime.UtcNow.AddSeconds(timeToLive), Cache.NoSlidingExpiration);
		}
		#endregion

		protected string GenerateUniquePageName(SPList listItem)
		{
			if (listItem == null)
				return null;

			throw new NotImplementedException();
		}

        protected void EnableModerationStatus(string siteUrl)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var site = new SPSite(siteUrl))
                using (var web = site.OpenWeb(GetWebUrl(site, siteUrl)))
                {
                    web.AllowUnsafeUpdates = true;
                    var pubWeb = PublishingWeb.GetPublishingWeb(web);
                    var pubList = pubWeb.PagesList;

                    if (pubList.EnableModeration)
                        return;

                    pubList.EnableModeration = true;
                    pubList.Update();
                }
            });
        }

	}
}